﻿using System;
using System.Data;
using System.Security.Cryptography;
using System.Text;
using System.Xml;

namespace com.uplus.common
{
    /// <summary>
    /// 数据转换服务类
    /// </summary>
    public static class DataConvert
    {
        #region XML->DT
        public static DataTable DataTableFromXmlString(string xmlString)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xmlString);
            DataTable dt = new DataTable();

            // 初始化列
            foreach (XmlNode item in doc.SelectSingleNode("//head"))
            {
                switch (item.Name[0])
                {
                    case 'n': dt.Columns.Add(item.Name.Substring(1), typeof(Decimal)); break;
                    case 't': dt.Columns.Add(item.Name.Substring(1), typeof(DateTime)); break;
                    case 'i': dt.Columns.Add(item.Name.Substring(2), typeof(Boolean)); break;
                    case 's': dt.Columns.Add(item.Name.Substring(1), typeof(String)); break;
                    default: throw new Exception("不支持的类型:" + item.Name[0]);
                }
            }

            foreach (XmlNode row in doc.SelectNodes("//item"))
            {
                DataRow r = dt.NewRow();
                foreach (XmlNode item in row.ChildNodes)
                {
                    switch (item.Name[0])
                    {
                        case 'n': if (!string.IsNullOrEmpty(item.InnerText)) r[item.Name.Substring(1)] = Convert.ToDecimal(item.InnerText); break;
                        case 's': r[item.Name.Substring(1)] = item.InnerText; break;
                        case 't': if (!string.IsNullOrEmpty(item.InnerText)) r[item.Name.Substring(1)] = DateTime.Parse(item.InnerText); break;
                        case 'i': if (!string.IsNullOrEmpty(item.InnerText)) r[item.Name.Substring(2)] = Convert.ToBoolean(item.InnerText); break;
                    }
                }
                dt.Rows.Add(r);
            }
            return dt;
        }
        #endregion

        #region DT->XML
        public static string DataTableToXmlString(DataTable dt)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(@"<?xml version=""1.0"" encoding=""utf-8"" ?>\r\n");
            sb.Append("<root>\r\n");
            sb.Append("<head>");
            foreach (DataColumn item in dt.Columns)
            {
                switch (item.DataType.Name)
                {
                    case "System.String": sb.AppendFormat("<s{0} />", item.ColumnName); break;

                    case "System.Int32":
                    case "System.Decimal":
                    case "System.Double": sb.AppendFormat("<n{0} />", item.ColumnName); break;

                    case "System.DateTime": sb.AppendFormat("<t{0} />", item.ColumnName); break;

                    case "System.Boolean": sb.AppendFormat("<is{0} />", item.ColumnName); break;
                }
            }
            sb.Append("</head>\r\n");

            foreach (DataRow item in dt.Rows)
            {
                sb.Append("<item>");

                foreach (DataColumn col in dt.Columns)
                {
                    object obj = item[col.ColumnName];
                    switch (obj.GetType().Name)
                    {
                        case "System.String": sb.AppendFormat("<s{0}><![CDATA[{1}]]></s{0}>", col.ColumnName, obj); break;

                        case "System.Int32":
                        case "System.Decimal":
                        case "System.Double": sb.AppendFormat("<n{0}>{1}</n{0}>", col.ColumnName, obj); break;

                        case "System.DateTime": sb.AppendFormat("<t{0}>{1}</t{0}>", col.ColumnName, obj); break;

                        case "System.Boolean": sb.AppendFormat("<is{0}>{1}</s{0}>", col.ColumnName, obj); break;
                    }
                }
                sb.Append("</item>");
            }
            sb.Append("\r\n</root>");

            return sb.ToString();
        }
        #endregion

        #region MD5加密
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="key">加密字符串</param>
        /// <returns>16位加密后的字符串(小写)</returns>
        public static string Md5(string key)
        {
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            string re = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.Default.GetBytes(key)), 4, 8);
            re = re.Replace("-", "");

            re = re.ToLower();

            return re;
        }

        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="key">加密的字符串</param>
        /// <param name="reCount">返回字符串的长度，值为16or32</param>
        /// <param name="isLower"></param>
        /// <returns>根据reCount和isLower返回MD5后的字符串</returns>
        public static string Md5(string key, int reCount, bool isLower)
        {
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            string re = "";
            switch (reCount)
            {
                case 16:
                    re = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key)), 4, 8);
                    break;
                case 32:
                    re = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key)));
                    break;
            }

            re = re.Replace("-", "");
            if (isLower)
            {
                re = re.ToLower();
            }
            return re;
        }
        #endregion

        #region DES加密
        /// <summary>
        /// 进行DES加密。
        /// </summary>
        /// <param name="pToEncrypt">要加密的字符串。</param>
        /// <param name="sKey">密钥，且必须为8位。</param>
        /// <returns>以16进制格式返回的加密字符串。</returns>
        public static string DESEncrypt(string pToEncrypt, string sKey)
        {
            using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
            {
                byte[] inputByteArray = Encoding.UTF8.GetBytes(pToEncrypt);
                des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
                des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
                des.Mode = CipherMode.ECB;
                des.Padding = PaddingMode.PKCS7;
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(inputByteArray, 0, inputByteArray.Length);
                    cs.FlushFinalBlock();
                    cs.Close();
                }
                //string str = Convert.ToBase64String(ms.ToArray());
                string str = ToHexString(ms.ToArray());


                ms.Close();
                return str;
            }
        }
        #endregion

        #region DES解密
        /// <summary>
        /// 进行DES解密
        /// </summary>
        /// <param name="pToDecrypt">要解密的16进制字符串</param>
        /// <param name="sKey">密钥，且必须为8位。</param>
        /// <returns>已解密的字符串</returns>
        public static string DESDecrypt(string pToDecrypt, string sKey)
        {
            //byte[] inputByteArray = Convert.FromBase64String(pToDecrypt);
            byte[] inputByteArray = ToDigitsBytes(pToDecrypt);
            using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
            {
                des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
                des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
                des.Mode = CipherMode.ECB;
                des.Padding = PaddingMode.PKCS7;
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write))
                {
                    try
                    {
                        cs.Write(inputByteArray, 0, inputByteArray.Length);
                        cs.FlushFinalBlock();
                        cs.Close();
                    }
                    catch
                    { }
                }
                string str = Encoding.UTF8.GetString(ms.ToArray());
                ms.Close();
                return str;
            }
        }


        /// <summary>
        /// 进行DES解密
        /// </summary>
        /// <param name="pToDecrypt">要解密的16进制字符串</param>
        /// <param name="sKey">密钥，且必须为8位。</param>
        /// <returns>已解密的字符串</returns>
        public static string DESDecrypt1(string pToDecrypt, string sKey)
        {
            //byte[] inputByteArray = Convert.FromBase64String(pToDecrypt);
            byte[] inputByteArray = ToDigitsBytes(pToDecrypt);
            using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
            {
                des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
                des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
                des.Mode = CipherMode.ECB;
                des.Padding = PaddingMode.PKCS7;
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write))
                {
                    try
                    {
                        cs.Write(inputByteArray, 0, inputByteArray.Length);
                        cs.FlushFinalBlock();
                        cs.Close();
                    }
                    catch
                    { }
                }
                string str = Encoding.Default.GetString(ms.ToArray());
                ms.Close();
                return str;
            }
        }
        #endregion

        #region AES加密
        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="toEncrypt">要加密的字符串</param>
        /// <param name="key">密钥，且必须为16位</param>
        /// <returns>以Base64格式返回的加密字符串。</returns>
        public static string AESEncrypt(string toEncrypt, string key)
        {
            byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
            byte[] ivArray = UTF8Encoding.UTF8.GetBytes(key);
            byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);

            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = keyArray;
            rDel.IV = ivArray;
            rDel.Mode = CipherMode.CBC;
            rDel.Padding = PaddingMode.PKCS7;

            ICryptoTransform cTransform = rDel.CreateEncryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
            return Convert.ToBase64String(resultArray, 0, resultArray.Length);

        }
        #endregion

        #region AES解密
        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="toDecrypt">需要解密的字符串</param>
        /// <param name="key">解密的密钥，且必须为16位</param>
        /// <returns>已解密的字符串</returns>
        public static string AESDecrypt(string toDecrypt, string key)
        {
            byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
            byte[] ivArray = UTF8Encoding.UTF8.GetBytes(key);
            byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);

            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = keyArray;
            rDel.IV = ivArray;
            rDel.Mode = CipherMode.CBC;
            rDel.Padding = PaddingMode.PKCS7;

            ICryptoTransform cTransform = rDel.CreateDecryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
            return UTF8Encoding.UTF8.GetString(resultArray);

        }
        #endregion

        //生成CRC32码表
        public static ulong[] GetCRC32Table()
        {
            ulong Crc;
            ulong[] Crc32Table = new ulong[256];
            int i, j;
            for (i = 0; i < 256; i++)
            {
                Crc = (ulong)i;
                for (j = 8; j > 0; j--)
                {
                    if ((Crc & 1) == 1)
                        Crc = (Crc >> 1) ^ 0xEDB88320;
                    else
                        Crc >>= 1;
                }
                Crc32Table[i] = Crc;
            }
            return Crc32Table;
        }

        //获取字符串的CRC32校验值
        public static string CRC32(string sInputString)
        {
            //生成码表
            var Crc32Table = GetCRC32Table();
            byte[] buffer = System.Text.ASCIIEncoding.ASCII.GetBytes(sInputString);
            ulong value = 0xffffffff;
            int len = buffer.Length;
            for (int i = 0; i < len; i++)
            {
                value = (value >> 8) ^ Crc32Table[(value & 0xFF) ^ buffer[i]];
            }
            return (value ^ 0xffffffff).ToString("X2").ToLower();
        }

        #region 字符数组、16进制字符串操作
        static char[] hexDigits = {
            '0','1','2','3','4','5','6','7',
            '8','9','A','B','C','D','E','F'};

        public static byte GetHexBitsValue(byte ch)
        {
            byte sz = 0;
            if (ch <= '9' && ch >= '0')
                sz = (byte)(ch - 0x30);
            if (ch <= 'F' && ch >= 'A')
                sz = (byte)(ch - 0x37);
            if (ch <= 'f' && ch >= 'a')
                sz = (byte)(ch - 0x57);

            return sz;
        }


        /// <summary>
        /// 字符数组转16进制字符串
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static string ToHexString(byte[] bytes)
        {
            char[] chars = new char[bytes.Length * 2];

            for (int i = 0; i < bytes.Length; i++)
            {
                int b = bytes[i];
                chars[i * 2] = hexDigits[b >> 4];
                chars[i * 2 + 1] = hexDigits[b & 0xF];
            }

            return new string(chars);
        }

        /// <summary>
        /// 16进制字符串转字符数组
        /// </summary>
        /// <param name="theHex"></param>
        /// <returns></returns>
        public static byte[] ToDigitsBytes(string theHex)
        {
            byte[] bytes = new byte[theHex.Length / 2 + (((theHex.Length % 2) > 0) ? 1 : 0)];
            for (int i = 0; i < bytes.Length; i++)
            {
                char lowbits = theHex[i * 2];
                char highbits;

                if ((i * 2 + 1) < theHex.Length)
                    highbits = theHex[i * 2 + 1];
                else
                    highbits = '0';

                int a = (int)GetHexBitsValue((byte)lowbits);
                int b = (int)GetHexBitsValue((byte)highbits);
                bytes[i] = (byte)((a << 4) + b);
            }

            return bytes;
        }
        #endregion

        #region
        //public static string DataTableToXmlString(DataTable dt)
        //{
        //    if (string.IsNullOrEmpty(dt.TableName)) dt.TableName = "Table";
        //    StringBuilder sb = new StringBuilder();
        //    using (XmlWriter xw = XmlWriter.Create(sb))
        //    {
        //        dt.WriteXml(xw);
        //        xw.Flush();
        //        xw.Close();
        //    }
        //    return sb.ToString();
        //}

        //public static DataTable DataTableFromXmlString(string xmlString, string tempPath)
        //{
        //    string f = string.Format(@"{0}\{1:yyyyMMddhhmmssfff}.xml", tempPath, DateTime.Now);
        //    XmlDocument doc = new XmlDocument();
        //    doc.LoadXml(xmlString);
        //    doc.Save(f);
        //    //File.WriteAllText(f, xmlString);
        //    DataSet ds = new DataSet();
        //    ds.ReadXml(f);
        //    File.Delete(f);
        //    return ds.Tables[0];
        //}
        #endregion

        #region 2进制string 转byte[]
        public static byte[] ToBytes(this string orgStr)
        {
            byte[] result = null;
            result = new byte[orgStr.Length];
            for(int i=0; i < orgStr.Length; i++)
            {
                //Console.WriteLine("ToBytes次数：" + i);
                //result[i] = Convert.ToByte(orgStr.Substring(i, 1));
                result[i] = Convert.ToByte(orgStr.Substring(orgStr.Length-1-i, 1));
            }
            return result;
        }
        #endregion


        #region 16进制转2进制
        public static string HexString2BinString(string hexString)
        {
            try
            {
                string result = string.Empty;
                foreach (char c in hexString)
                {
                    int v = Convert.ToInt32(c.ToString(), 16);
                    int v2 = int.Parse(Convert.ToString(v, 2));
                    // 去掉格式串中的空格，即可去掉每个4位二进制数之间的空格，
                    result += string.Format("{0:d4} ", v2);
                }
                return result;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                throw;
            }
        }
        #endregion
    }
}
